<template>
  <div>
    <slot
    v-if="custom"
    name="countdown"
    :totalHours="totalHours"
    :days="days"
    :hours="hours"
    :minutes="minutes"
    :seconds="seconds"
     ></slot>
    <div
    v-else
    :class="time"
    :style="{ color: color, fontSize: fontSize+'rpx' }"
    >{{ prefix }}{{ formattedTime }}{{ suffix }}
    </div>
  </div>
</template>

<script>
import { parseTimeData, parseFormat, isSameSecond } from './utils';

function tick(fn) {
  return setTimeout(fn, 30);
}

export default {
  name: 'CountDown',
  props: {
    // 是否使用自定义样式
    custom: {
      type: Boolean,
      default: false,
    },
    // 是否自动开始倒计时
    autoplay: {
      type: Boolean,
      default: true,
    },
    color: {
       type: String,
       default: '#333333'
    },
    fontSize: {
      type: Number,
      default: 28
    },
    // 是否开启毫秒级渲染,配合format[SSS]才能显示毫秒
    millisecond: {
      type: Boolean,
      default: false,
    },
    // 倒计时时长，单位毫秒
    time: {
      type: Number,
      required: true,
    },
    // 时间格式，DD-日，HH-时，mm-分，ss-秒，SSS-毫秒
    format: {
      type: String,
      default: 'HH:mm:ss',
    },
    prefix: {
      type: String,
      default: '',
    },
    suffix: {
      type: String,
      default: '',
    },
  },
  computed: {
    days() {
      if (this.format.indexOf('DD') > -1) {

        return this.formattedTime.split('天')[0]
      }

      return 0
    },
    hours() {
      if (this.format.indexOf('DD') > -1) {
        let  daysAndHours = this.formattedTime.split('天');
        return daysAndHours[1] && daysAndHours[1].split(':')[0]
      }

      return this.formattedTime.split(':')[0]
    },
    totalHours() {
      return Number(this.days * 24) + Number(this.hours);
    },
    minutes() {
      return this.formattedTime.split(':')[1]
    },
    seconds() {
      return this.formattedTime.split(':')[2]
    },

  },
  data() {
    return {
      timeData: '123',
      formattedTime: '',
      counting: false,
      endTime: '',
      remain: 0,
      timer: null
    };
  },
  mounted() {
    //页面渲染问题——先言辞处理
    setTimeout(() => {
       this.$nextTick(() => {
         this.init();
       })
    }, 1000)
  },
  beforeDestroy() {
    this.pause();
  },
  methods: {
    init() {
      this.pause();
      this.remain = this.time;
      this.setRemain(this.remain);
      if (this.autoplay) {
        this.start();
      }
    },
    start() {
      if (this.counting) {
        return;
      }
      this.counting = true;
      this.endTime = Date.now() + this.remain;
      this.tick();
    },
    pause() {
      this.counting = false;
      clearTimeout(this.timer);
      this.timer = null;
    },
    tick() {
      if (this.millisecond) {
        this.microTick();
      } else {
        this.macroTick();
      }
    },
    microTick() {
      this.timer = tick(() => {
        this.setRemain(this.getRemain());
        if (this.remain !== 0) {
          this.microTick();
        }
      });
    },
    macroTick() {
      this.timer = tick(() => {
        const remain = this.getRemain();
        // 秒数相同或者剩余时间为0时不更新UI
        if (!isSameSecond(remain, this.remain) || remain === 0) {
          this.setRemain(remain);
        }
        if (this.remain !== 0) {
          this.macroTick();
        }
      });
    },
    getRemain() {
      return Math.max(this.endTime - Date.now(), 0);
    },
    setRemain(remain) {
      this.remain = remain;
      const timeData = parseTimeData(this.remain);
      this.timeData = timeData;
      this.formattedTime = parseFormat(this.format, timeData);
      if (remain <= 1000) {
        this.pause();
        this.$emit('finish');
      }
    },
  },
};
</script>

<style scoped lang="less">

</style>
